////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//         This file is distributed under the BSD 2-Clause open source license. See Licenses/License.txt for details.         //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


#ifndef __WN_SCRIPTING_ENGINE_H__
#define __WN_SCRIPTING_ENGINE_H__

#include "WNCore/inc/WNTypes.h"
#include "WNScripting/inc/WNTypeElement.h"
#include "WNScripting/inc/WNScriptingErrors.h"
#include "WNContainers/inc/WNCallback.h"
#include "WNLogging/inc/WNLog.h"

namespace WNScripting {
    template<typename T>
    struct TypeMapping {
        static const WN_CHAR * GetTypeName() { WN_STATIC_ASSERT(WN_STATIC_ASSERT_DEPENDENT_FAIL<T>::Value); } 
    };
}
    #define DEFINE_TEMPLATE_MAPPING(type, name) \
        namespace WNScripting { \
        template<> \
        struct TypeMapping<type> { \
            static const WN_CHAR * GetTypeName() { return #name; } \
        }; \
        } 

DEFINE_TEMPLATE_MAPPING(WN_INT32, Int);
DEFINE_TEMPLATE_MAPPING(WN_FLOAT32, Float);
DEFINE_TEMPLATE_MAPPING(WN_CHAR, Char);
DEFINE_TEMPLATE_MAPPING(WN_BOOL, Bool);
DEFINE_TEMPLATE_MAPPING(WN_VOID, Void);
DEFINE_TEMPLATE_MAPPING(WN_VOID*, -Ptr);
DEFINE_TEMPLATE_MAPPING(WN_SIZE_T, -SizeT);

#include <vector>
namespace WNScripting {
    struct WNParameter;
    typedef WNContainers::WNCallback3<WN_VOID, const WN_CHAR*, WN_SIZE_T, const std::vector<WNLogging::WNLogColorElement>&> WNScriptingLogCallback;
    class WNScriptingEngine {
    public:
        virtual ~WNScriptingEngine() {}
        //virtual WN_BOOL AddExternalFunction(WN_VOID* _funcPtr, WN_BOOL _stackRet, const WN_CHAR* _returnType, const WN_CHAR* _name, const WN_CHAR* _arglist) = 0;
        virtual eWNTypeError GetFunctionPointer(const WN_CHAR* _file, const WN_CHAR* _functionName, const WNScriptType _retParam, const std::vector<WNScriptType>& _params, void*& _ptr) = 0;
        virtual eWNTypeError Initialize() = 0;
        virtual WNScriptType GetTypeByName(const WN_CHAR* _typeName) = 0;
        virtual eWNTypeError RegisterFunction(const WN_CHAR* _functionName, const WNScriptType _retParam, const std::vector<WNScriptType>& _params, void* _ptr) = 0;
        virtual void* GetRegisteredFunction(const WN_CHAR* _functionName) const = 0;
        virtual void SetInternalLogLevel(WNLogging::WNLogLevel) = 0;
        virtual void SetLogLevel(WNLogging::WNLogLevel) = 0;
        virtual void SetCompilationLog(WNLogging::WNLog*) = 0;
        template<typename R> 
        eWNTypeError GetPointerToFunction(const WN_CHAR* _file, const WN_CHAR* _functionName, R (*&_outPtr)());
        template<typename R, typename T1> 
        eWNTypeError GetPointerToFunction(const WN_CHAR* _file, const WN_CHAR* _functionName, R (*&_outPtr)(T1));
        template<typename R, typename T1, typename T2> 
        eWNTypeError GetPointerToFunction(const WN_CHAR* _file, const WN_CHAR* _functionName, R (*&_outPtr)(T1, T2));
        template<typename R, typename T1, typename T2, typename T3> 
        eWNTypeError GetPointerToFunction(const WN_CHAR* _file, const WN_CHAR* _functionName, R (*&_outPtr)(T1, T2, T3));
        template<typename R, typename T1, typename T2, typename T3, typename T4> 
        eWNTypeError GetPointerToFunction(const WN_CHAR* _file, const WN_CHAR* _functionName, R (*&_outPtr)(T1, T2, T3, T4));
        template<typename R, typename T1, typename T2, typename T3, typename T4, typename T5> 
        eWNTypeError GetPointerToFunction(const WN_CHAR* _file, const WN_CHAR* _functionName, R (*&_outPtr)(T1, T2, T3, T4, T5));
        template<typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> 
        eWNTypeError GetPointerToFunction(const WN_CHAR* _file, const WN_CHAR* _functionName, R (*&_outPtr)(T1, T2, T3, T4, T5, T6));

        template<typename R>
        eWNTypeError RegisterCFunction(const WN_CHAR* _name, R (*_ptr)());
        template<typename R, typename T1>
        eWNTypeError RegisterCFunction(const WN_CHAR* _name, R (*_ptr)(T1));
        template<typename R, typename T1, typename T2>
        eWNTypeError RegisterCFunction(const WN_CHAR* _name, R (*_ptr)(T1, T2));
        template<typename R, typename T1, typename T2, typename T3>
        eWNTypeError RegisterCFunction(const WN_CHAR* _name, R (*_ptr)(T1, T2, T3));
        template<typename R, typename T1, typename T2, typename T3, typename T4>
        eWNTypeError RegisterCFunction(const WN_CHAR* _name, R (*_ptr)(T1, T2, T3, T4));
        template<typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
        eWNTypeError RegisterCFunction(const WN_CHAR* _name, R (*_ptr)(T1, T2, T3, T4, T5));
        template<typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
        eWNTypeError RegisterCFunction(const WN_CHAR* _name, R (*_ptr)(T1, T2, T3, T4, T5, T6));
    };
}
#include "WNFunctionTemplates.inl"
#endif//__WN_SCRIPTING_ENGINE_H__ 
